package stud.cp.user.plugins.designer;

import java.math.BigInteger;
import java.util.List;

import javax.ejb.Stateless;
import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;

import stud.cp.core.dbaccess.DAOException;
import stud.cp.core.plugins.PluginConst;
import stud.cp.core.plugins.PluginRouter;
import stud.cp.core.plugins.WrongPageRequest;
import stud.cp.user.dbaccess.ObjectDAO;
import stud.cp.user.dbaccess.ObjectTypesPropertiesDAO;
import stud.cp.user.dbaccess.OracleDAOFactory;
import stud.cp.user.valueobjects.*;

/**
 * Имплементация логики работы с типами продуктов.
 */
@Stateless
public class ProductTypesPluginBean implements ProductTypesPluginBeanLocal {

    /**
     * Фабрика DAO классов.
     */
    private OracleDAOFactory oracleDAOFactory = null;
    /**
     * Логгер.
     */
    private static Logger logger = Logger.getLogger("ACPII");

    /**
     * Метод, выполняющий бизнес логику плагина.
     *
     * @param req Реквест.
     * @return Класс плагин.
     */
    @Override
    public PluginRouter perform(HttpServletRequest req) {
        String subaction = req.getParameter(PluginConst.SUBACTION);


        if ((subaction != null) && (!subaction.equals(""))) {
            try {

                oracleDAOFactory = new OracleDAOFactory();
                oracleDAOFactory.initialize();
                /*
                 * Список действий которые могут выполниться.
                 */

                if (subaction.equals(PluginConst.GET_LIST)) {
                    return getListOfProductTypes(req);
                }

                /*
                 * Страница добавления
                 */
                if (subaction.equals(PluginConst.GET_ADD_PAGE)) {
                    return getAddPage(req);
                }

                /*
                 * Добавление новых данных
                 */
                if (subaction.equals(PluginConst.NEW_DATA)) {
                    return newData(req);
                }

                /*
                 * Страница редактирования
                 */
                if (subaction.equals(PluginConst.GET_EDIT_PAGE)) {
                    return getEditPage(req);
                }

                /*
                 * Сохранение измененных данных
                 */
                if (subaction.equals(PluginConst.SAVE_DATA)) {
                    return saveData(req);
                }

                /*
                 * Страница удаления
                 */
                if (subaction.equals(PluginConst.GET_DELETE_PAGE)) {
                    return getDeletePage(req);
                }

                /*
                 * Удаление данные
                 */
                if (subaction.equals(PluginConst.DELETE_DATA)) {
                    return deleteData(req);
                }


                if (subaction.equals(PluginConst.TEMPORARY_DELETE)) {
                    return temporaryDeleteData(req);
                }
                //
                //                /*Страница просмотра данных о типе оружия*/
                //                if (subaction.equals(PluginConst.GET_VIEW_PAGE)) {
                //                    return getViewPage(req);
                //                }
                //
                //                /*Страница со списком свойств, принадлежащий данному типу оружия.*/
                //                if (subaction.equals(PluginConst.GET_WEAPON_TYPE_PROPERTIES_LIST)) {
                //                    return getObjectTypePropertyListPage(req);
                //                }
                //
                //                /*Страница с диалогом для пользователя, который хочет исключить свойство из типа оружия.*/
                //                if (subaction.equals(PluginConst.EXCLUDE_PROPERTY_FROM_WEAPON_TYPE_PAGE)) {
                //                    return getExcludePropertyFromObjectTypePage(req);
                //                }
                //
                //                /*Исключение свойства из объектного типа.*/
                //                if (subaction.equals(PluginConst.EXCLUDE_PROPERTY_FROM_WEAPON_TYPE)) {
                //                    return excludePropertyFromObjectType(req);
                //                }
                //
                //                /*Страница добавления свойств к типу оружия.*/
                //                if (subaction.equals(PluginConst.ADD_PROPERTIES_TO_WEAPON_TYPE_PAGE)) {
                //                    return getAddPropertiesToObjectTypePage(req);
                //                }
                //
                //                /*Добавление свойств к объектному типу*/
                //                if (subaction.equals(PluginConst.ADD_PROPERTIES_TO_WEAPON_TYPE)) {
                //                    return addPropertiesToObjectType(req);
                //                }

                req.setAttribute(PluginConst.ERROR_MESSAGE,
                        "Действия для данного типа поддействия не найдено. Тип поддействия = " + subaction);
            } catch (DAOException ex) {
                logger.debug("Error due access to database. "
                        + "Plugin = ProductTypesPluginBean. "
                        + "Subaction=" + subaction, ex);
                req.setAttribute(PluginConst.ERROR_MESSAGE,
                        "Ошибка доступа к базе данных " + ex.getMessage());
            } catch (WrongPageRequest ex) {
                req.setAttribute(PluginConst.ERROR_MESSAGE,
                        "Данные из реквеста ошибочны :\n" + ex.getMessage());
            } catch (NumberFormatException ex) {
                req.setAttribute(PluginConst.ERROR_MESSAGE,
                        "ID объекта не имеет числовой формат :\n" + ex.getMessage());
            } finally {

                if (oracleDAOFactory != null) {
                    try {
                        oracleDAOFactory.cleanUp();
                    } catch (DAOException ex) {
                        logger.debug("Error due access to database. "
                                + "Plugin = ProductTypesPluginBean. "
                                + "Subaction=" + subaction, ex);
                        req.setAttribute(PluginConst.ERROR_MESSAGE,
                                "Ошибка доступа к базе данных " + ex.getMessage());
                    }
                }
            }
        } else {
            req.setAttribute(PluginConst.ERROR_MESSAGE,
                    "Тип поддействия не задан.");
        }

        return new PluginRouter("/errorpage.jsp");
    }

    private PluginRouter getListOfProductTypes(HttpServletRequest req) throws DAOException, WrongPageRequest {
        List<DBObjectType> listOfDBObjectTypes =
                oracleDAOFactory.getObjectTypesDAO().getObjectTypeHeirsButNotDelete(PluginConst.PRODUCTS_OBJECT_TYPE_ID);
        req.setAttribute(PluginConst.OBJECT_TYPE_LIST, listOfDBObjectTypes);
        return new PluginRouter("/Designer/ProductTypes/ProductTypesTable.jsp");
    }

    //    List<DBObject> listOfDBObjects =
    //            oracleDAOFactory.getObjectDAO().getAllObjectByObjectType(objectTypeId);
    //    req.setAttribute(DesignerPluginConst.OBJECT_HEIRS_LIST, listOfDBObjects);
    //    return new PluginRouter("/Designer/Products/ProductsTable.jsp");
    private PluginRouter getAddPage(HttpServletRequest req) throws DAOException, WrongPageRequest {
        return new PluginRouter("/Designer/ProductTypes/AddProductType.jsp");
    }

    /**
     * Метод, позволяющий добавлять новые данные.
     *
     * @param req Реквест.
     * @return PluginRouter c запрашиваемой страницей.
     * @throws DAOException Ошибка доступа к базе данных.
     * @throws WrongPageRequest Критическая ошибка в данных реквеста.
     */
    private PluginRouter newData(HttpServletRequest req) throws DAOException, WrongPageRequest {
        String name = req.getParameter(PluginConst.OBJECT_TYPE_NAME);
        String description = req.getParameter(PluginConst.OBJECT_TYPE_DESCRIPTION);

        BigInteger object_type_id = oracleDAOFactory.getObjectTypesDAO().
                create(new DBObjectType(name, description, PluginConst.PRODUCTS_OBJECT_TYPE_ID, false));

        ObjectTypesPropertiesDAO wtpdao = oracleDAOFactory.getObjectTypesPropertiesDAO();
        wtpdao.create(new DBObjectTypesProperties(PluginConst.COST_PROPERTY_ID, object_type_id));
        wtpdao.create(new DBObjectTypesProperties(PluginConst.STORE_TYPE_PROPERTY_ID, object_type_id));

        return new PluginRouter("products-action.do"
                + "?"
                + PluginConst.SUBACTION
                + "="
                + PluginConst.GET_LIST
                + "&"
                + PluginConst.OBJECT_TYPE_ID
                + "="
                + object_type_id, false);
    }

    /**
     * Метод, который позволяет перейти на страницу удаления элемента.
     *
     * @param req Реквест.
     * @return PluginRouter c запрашиваемой страницей.
     * @throws DAOException Ошибка доступа к базе данных.
     * @throws WrongPageRequest Критическая ошибка в данных реквеста.
     */
    private PluginRouter getDeletePage(HttpServletRequest req) throws DAOException, WrongPageRequest {
        String objectTypeIdValue = req.getParameter(PluginConst.OBJECT_TYPE_ID);
        if ((objectTypeIdValue == null) || (objectTypeIdValue.equals(""))) {
            throw new WrongPageRequest("ID объекта не занад!");
        }
        BigInteger objectTypeId =
                new BigInteger(objectTypeIdValue);
        DBObjectType objectType = oracleDAOFactory.getObjectTypesDAO().getById(objectTypeId);
        if (objectType != null) {


            String errorMessage = "";
            ObjectDAO objectDAO = oracleDAOFactory.getObjectDAO();
            DBObject dbObject;

            List<DBObject> productList =
                    oracleDAOFactory.getObjectDAO().getAllObjectByObjectTypeButNotDelete(objectTypeId);
            for (DBObject product : productList) {
                List<DBObjectReference> listOfReferenceOnObject = oracleDAOFactory.getObjectReferencesDAO().
                        getAllReferenceOnObjectWithPropertyIDButNotNull(product.getObject_id(), PluginConst.LINK_ON_PRODUCT_PRODPERTY_ID);

                if (listOfReferenceOnObject.size() != 0) {
                    errorMessage += "Продукт \"" + product.getName() + "\" находиться в рецепте следующих продуктов: <br/>";
                    for (DBObjectReference referenceOnObject : listOfReferenceOnObject) {
                        dbObject = objectDAO.getById(referenceOnObject.getObject_id());
                        errorMessage += dbObject.getName() + "</br>";
                    }
                }
                Parameter amountParam = oracleDAOFactory.getParameterDAO().getParameterByIdForObject(PluginConst.STORE_TYPE_PROPERTY_ID, product.getObject_id());
                if (Double.valueOf(amountParam.getValue()) != 0) {
                    errorMessage += ("Для удаления продукта из списка его запас на складе должен равняться нулю, а не = " + amountParam.getValue() + ".<br/>");
                }

            }

            if (!errorMessage.equals("")) {
                if (errorMessage.contains("Продукт")) {
                    errorMessage = "Продукты данного типа продукта находяться в рецептах блюд:<br/>" + errorMessage;
                }
                req.setAttribute(PluginConst.ERROR_MESSAGE, errorMessage);
            }

            req.setAttribute(PluginConst.OBJECT_TYPE, objectType);
            return new PluginRouter("/Designer/ProductTypes/DeleteProductType.jsp");
        } else {
            throw new WrongPageRequest("Тип оружия с таким id=" + objectTypeId + " не существует. ");
        }

    }

    /**
     * Метод, удаляющий данные из базы данных.
     *
     * @param req Реквест.
     * @return PluginRouter c запрашиваемой страницей.
     * @throws DAOException Ошибка доступа к базе данных.
     * @throws WrongPageRequest Критическая ошибка в данных реквеста.
     */
    private PluginRouter deleteData(HttpServletRequest req) throws DAOException, WrongPageRequest {
        String objectTypeIdValue = req.getParameter(PluginConst.OBJECT_TYPE_ID);
        if ((objectTypeIdValue == null) || (objectTypeIdValue.equals(""))) {
            throw new WrongPageRequest("ID объекта не занад!");
        }
        BigInteger objectTypeId =
                new BigInteger(objectTypeIdValue);

        DBObjectType objectType = oracleDAOFactory.getObjectTypesDAO().getById(objectTypeId);
        if (objectType != null) {
            oracleDAOFactory.getObjectTypesDAO().delete(objectType.getObject_type_id());
            return new PluginRouter("product-types-action.do"
                    + "?"
                    + PluginConst.SUBACTION
                    + "="
                    + PluginConst.GET_LIST, false);
        } else {
            throw new WrongPageRequest("Тип оружия с таким id=" + objectTypeId + " не существует. ");
        }

    }

    /**
     * Метод, который позволяет перейти на страницу редактирования данных.
     *
     * @param req Реквест.
     * @return PluginRouter c запрашиваемой страницей.
     * @throws DAOException Ошибка доступа к базе данных.
     * @throws WrongPageRequest Критическая ошибка в данных реквеста.
     */
    private PluginRouter getEditPage(HttpServletRequest req) throws DAOException, WrongPageRequest {
        String objectTypeIdValue = req.getParameter(PluginConst.OBJECT_TYPE_ID);
        if ((objectTypeIdValue == null) || (objectTypeIdValue.equals(""))) {
            throw new WrongPageRequest("ID объекта не занад!");
        }
        BigInteger objectTypeId =
                new BigInteger(objectTypeIdValue);

        DBObjectType objectType = oracleDAOFactory.getObjectTypesDAO().getById(objectTypeId);
        if (objectType != null) {
            req.setAttribute(PluginConst.OBJECT_TYPE, objectType);
            return new PluginRouter("/Designer/ProductTypes/EditProductType.jsp");
        } else {
            throw new WrongPageRequest("Тип оружия с таким id=" + objectTypeId + " не существует. ");
        }

    }

    /**
     * Сохранение данных.
     *
     * @param req Реквест.
     * @return PluginRouter c запрашиваемой страницей.
     * @throws DAOException Ошибка доступа к базе данных.
     * @throws WrongPageRequest Критическая ошибка в данных реквеста.
     */
    private PluginRouter saveData(HttpServletRequest req) throws DAOException, WrongPageRequest {
        String name = req.getParameter(PluginConst.OBJECT_TYPE_NAME);
        String description = req.getParameter(PluginConst.OBJECT_TYPE_DESCRIPTION);
        String objectTypeIdValue = req.getParameter(PluginConst.OBJECT_TYPE_ID);
        logger.debug("Test = " + objectTypeIdValue);
        if ((objectTypeIdValue == null) || (objectTypeIdValue.equals(""))) {
            throw new WrongPageRequest("ID объекта не занад!");
        }
        BigInteger objectTypeId =
                new BigInteger(objectTypeIdValue);

        DBObjectType objectType = oracleDAOFactory.getObjectTypesDAO().getById(objectTypeId);
        if (objectType != null) {
            objectType.setName(name);
            objectType.setDescription(description);
            oracleDAOFactory.getObjectTypesDAO().update(objectType);
            return new PluginRouter("product-types-action.do"
                    + "?"
                    + PluginConst.SUBACTION
                    + "="
                    + PluginConst.GET_LIST, false);
        } else {
            throw new WrongPageRequest("Тип оружия с таким id=" + objectTypeId + " не существует. ");
        }

    }

    private PluginRouter temporaryDeleteData(HttpServletRequest req) throws WrongPageRequest, DAOException {
        String objectTypeIdValue = req.getParameter(PluginConst.OBJECT_TYPE_ID);
        if ((objectTypeIdValue == null) || (objectTypeIdValue.equals(""))) {
            throw new WrongPageRequest("ID объекта не занад!");
        }
        BigInteger objectTypeId =
                new BigInteger(objectTypeIdValue);

        DBObjectType objectType = oracleDAOFactory.getObjectTypesDAO().getById(objectTypeId);
        if (objectType != null) {
            objectType.setName("[Удалено]" + objectType.getName());
            objectType.setIsTemporaryDelete(Boolean.TRUE);
            oracleDAOFactory.getObjectTypesDAO().update(objectType);

            ObjectDAO objectDAO = oracleDAOFactory.getObjectDAO();

            List<DBObject> listOfProducts = objectDAO.getAllObjectByObjectType(objectTypeId);

            for (DBObject product : listOfProducts) {
                product.setIsDelete(Boolean.TRUE);
                objectDAO.update(product);
            }


            return new PluginRouter("product-types-action.do"
                    + "?"
                    + PluginConst.SUBACTION
                    + "="
                    + PluginConst.GET_LIST, false);
        } else {
            throw new WrongPageRequest("Тип оружия с таким id=" + objectTypeId + " не существует. ");
        }
    }
}
